// ??? // Idols and Fans // Author: Constantine Sokol // Complexity : O( N + Q * ( log N ) ** 2 ) // Expected Verdict: AC #include #include #include #include #include using namespace std; const int maxn = 100000 + 5; int n, q, _p[ maxn ], _a[ maxn ]; //--------------------------------------- pair< int, int > operator+( pair< int, int > a, pair< int, int > b ) { if ( a.first > b.first ) return a; if ( a.first < b.first ) return b; return make_pair( a.first, a.second + b.second ); } //--------------------------------------- struct seg_tree { pair< int, int > tree[ 4 * maxn ]; void modify( int v, int l, int r, int pos, int value ) { if ( l == r ) { tree[v].first = value; tree[v].second = 1; return; } int x = (l + r) / 2; if ( pos <= x ) modify( v + v, l, x, pos, value ); else modify( v + v + 1, x + 1, r, pos, value ); tree[v] = tree[v + v] + tree[v + v + 1]; } pair< int, int > query( int v, int ll, int rr, int l, int r ) { if ( ll == l && r == rr ) return tree[v]; int xx = (ll + rr) / 2; pair< int, int > result( -maxn, 0 ); if ( l <= xx ) result = result + query( v + v, ll, xx, l, min( xx, r ) ); if ( xx + 1 <= r ) result = result + query( v + v + 1, xx + 1, rr, max( xx + 1, l ), r ); return result; } }; struct heavy_light { // Graph block int n; vector< int > graph[ maxn ]; int depth[ maxn ]; // HLDOT block int path_id[ maxn ], leader[ maxn ], subtree[ maxn ]; int current_id, pos[ maxn ], current_pos[ maxn ], max_depth, heavy_child[ maxn ]; seg_tree st; //--------------------------------------- void add_edge( int a, int b ) { graph[a].push_back(b); } void init() { for ( int v = 1; v <= n; v++ ) { subtree[v] = 1; for ( int i = 0; i < graph[v].size(); i++ ) { int next = graph[v][i]; depth[next] = depth[v] + 1; } } for ( int v = n; v > 1; v-- ) { int prev = _p[ v ]; subtree[ prev ] += subtree[ v ]; } for ( int v = 1; v <= n; v++ ) { heavy_child[v] = -1; for ( int i = 0; i < graph[v].size(); i++ ) { int next = graph[v][i]; if ( 2 * subtree[ next ] >= subtree[ v ] ) heavy_child[v] = next; } } leader[1] = 1; path_id[1] = 1; current_id = 1; current_pos[1] = 1; for ( int v = 1; v <= n; v++ ) { pos[v] = current_pos[v]; current_pos[v] += 1; if ( heavy_child[v] != -1 ) { path_id[ heavy_child[v] ] = path_id[ v ]; current_pos[ heavy_child[v] ] = current_pos[v]; current_pos[v] += subtree[ heavy_child[v] ]; } for ( int i = 0; i < graph[v].size(); i++ ) { int next = graph[v][i]; if ( next == heavy_child[v] ) continue; leader[ ++current_id ] = next; path_id[ next ] = current_id; current_pos[ next ] = current_pos[ v ]; current_pos[ v ] += subtree[ next ]; } } } void decompose() { init(); for ( int i = 1; i <= n; i++ ) st.modify( 1, 1, n, pos[i], _a[i] - depth[i] ); } void modify( int v, int new_value ) { st.modify( 1, 1, n, pos[v], new_value - depth[v] ); _a[v] = new_value; } pair< int, int > query( int v ) { pair< int, int > result( -maxn, 0 ); int mem = depth[v]; while ( true ) { if ( leader[ path_id[v] ] == 1 ) { result = result + st.query( 1, 1, n, pos[1], pos[v] ); break; } result = result + st.query( 1, 1, n, pos[ leader[ path_id[v] ] ], pos[ v ] ); v = _p[ leader[ path_id[v] ] ]; } return make_pair( result.first + mem, result.second ); } }; heavy_light hl; int main() { scanf("%d%d", &n, &q); hl.n = n; for ( int i = 1; i <= n; i++ ) scanf("%d", &_a[i]); _p[1] = 1; for ( int i = 2; i <= n; i++ ) { scanf("%d", &_p[i]); hl.add_edge( _p[i], i ); } hl.decompose(); for ( int it = 1; it <= q; it++ ) { int _type; scanf("%d", &_type); if ( _type == 0 ) { int v, value; scanf("%d%d", &v, &value); hl.modify( v, value ); } if ( _type == 1 ) { int v; scanf("%d", &v); pair< int, int > result = hl.query( v ); printf("%d %d\n", result.first, result.second); } } return 0; }